package com.niiwoo.civet.mobile.controller.loan;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.account.dto.common.BankCardDTO;
import com.niiwoo.civet.account.dto.common.BankTypeDTO;
import com.niiwoo.civet.account.service.bankcard.BankCardDubboService;
import com.niiwoo.civet.mobile.vo.common.BankCardVO;
import com.niiwoo.civet.mobile.vo.common.BankTypeVO;
import com.niiwoo.civet.mobile.vo.request.LoanReConfirmSubmitReqVO;
import com.niiwoo.civet.mobile.vo.request.loan.LoanAuditConfirmReqVO;
import com.niiwoo.civet.mobile.vo.request.loan.LoanBackSubmitReqVO;
import com.niiwoo.civet.mobile.vo.request.loan.LoanFeeCalculationRequestDTO;
import com.niiwoo.civet.mobile.vo.request.loan.LoanRepaymentPlanRequestDTO;
import com.niiwoo.civet.mobile.vo.request.loan.LoanSubmitCommReqVO;
import com.niiwoo.civet.mobile.vo.request.loan.LoanSubmitReqVO;
import com.niiwoo.civet.mobile.vo.response.loan.LoanConfigResVO;
import com.niiwoo.civet.mobile.vo.response.loan.LoanFeeCalculationResponseVO;
import com.niiwoo.civet.mobile.vo.response.loan.LoanSubmitCommResVO;
import com.niiwoo.civet.mobile.vo.response.loan.RepaymentPlanResponseVO;
import com.niiwoo.civet.trade.dto.request.loan.ConfirmLoanRepaymentPlanRequestDTO;
import com.niiwoo.civet.trade.dto.request.loan.ConfirmLoanRequestDTO;
import com.niiwoo.civet.trade.dto.request.loan.LoanAuditConfirmReqDTO;
import com.niiwoo.civet.trade.dto.request.loan.LoanBackSubmitReqDTO;
import com.niiwoo.civet.trade.dto.request.loan.LoanConfigReqDTO;
import com.niiwoo.civet.trade.dto.request.loan.LoanReConfirmSubmitReqDTO;
import com.niiwoo.civet.trade.dto.request.loan.LoanSubmitCommReqDTO;
import com.niiwoo.civet.trade.dto.request.loan.LoanSubmitReqDTO;
import com.niiwoo.civet.trade.dto.request.loan.RepaymentPlanDTO;
import com.niiwoo.civet.trade.dto.response.loan.ConfirmResponseDTO;
import com.niiwoo.civet.trade.dto.response.loan.LoanConfigResDTO;
import com.niiwoo.civet.trade.dto.response.loan.LoanSubmitCommResDTO;
import com.niiwoo.civet.trade.enums.LoanSubmitTypeEnum;
import com.niiwoo.civet.trade.enums.ProjectTypeEnum;
import com.niiwoo.civet.trade.service.loan.ConsumeLoanDubboService;
import com.niiwoo.civet.trade.service.loan.LoanSubmitDubboService;
import com.niiwoo.civet.trade.service.loan.SpeedLoanDubboService;
import com.niiwoo.tripod.web.util.PrincipalContext;
import com.niiwoo.tripod.web.util.RequestUtil;
import com.niiwoo.tripod.web.vo.Result;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@RestController
@RequestMapping("/consumeloan")
@Api(tags = "[5.5.8][贾波]消费贷借款申请流程")
public class ConsumeLoanController {

    @Reference(version = "1.0.0")
    private LoanSubmitDubboService loanSubmitDubboService;
    
    @Reference(version = "1.0.0")
    private ConsumeLoanDubboService consumeLoanDubboService;
    
    @Reference(version = "1.0.0")
    private BankCardDubboService bankCardDubboService;
    
    @Reference(version = "1.0.0")
    private SpeedLoanDubboService speedLoanService;    
    
    @PostMapping("/loanCheck")
    @ApiOperation("消费贷申请较验")
    public Result<LoanSubmitCommResVO> loanCheck(@RequestBody @Valid LoanSubmitCommReqVO loanSubmitCommReqVO) {
		LoanSubmitCommReqDTO reqDTO = new LoanSubmitCommReqDTO();
		BeanUtils.copyProperties(loanSubmitCommReqVO, reqDTO);
		reqDTO.setUserId(PrincipalContext.getUserId());
		reqDTO.setLoanSubmitTypeEnum(LoanSubmitTypeEnum.CONSUME_LOAN);
		LoanSubmitCommResDTO resDTO = loanSubmitDubboService.loanCheck(reqDTO);
		return Result.with(obtainLoanSubmitCommResVO(resDTO));
    }
    
    @PostMapping("/loanConfig")
    @ApiOperation("消费借款配置")
    public Result<LoanConfigResVO> loanConfig() {
        LoanConfigReqDTO reqDTO = new LoanConfigReqDTO();
        reqDTO.setUserId(PrincipalContext.getUserId());
        reqDTO.setLoanSubmitTypeEnum(LoanSubmitTypeEnum.CONSUME_LOAN);
        LoanConfigResDTO loanConfigResDTO = loanSubmitDubboService.loanConfig(reqDTO);
		LoanConfigResVO vo = JSON.parseObject(JSON.toJSONString(loanConfigResDTO), LoanConfigResVO.class);
        return Result.with(vo);
    }    
    
    @PostMapping("costCalculation")
    @ApiOperation("消费贷借款费用计算")
    public Result<LoanFeeCalculationResponseVO> creditCardLoanCostCalculation(@RequestBody @Valid LoanFeeCalculationRequestDTO request) {
    	String userId = PrincipalContext.getUserId();
    	
    	// 构建请求参数
		ConfirmLoanRequestDTO loanConfirmRequestDTO = new ConfirmLoanRequestDTO();
		loanConfirmRequestDTO.setUserId(userId);
		loanConfirmRequestDTO.setLoanAmount(request.getLoanAmount());
		loanConfirmRequestDTO.setLoanTerm(request.getLoanTerm());
		loanConfirmRequestDTO.setLoanUsage(request.getLoanUsage());
		loanConfirmRequestDTO.setConfigType(ProjectTypeEnum.CONSUME_LOAN.getValue());
        
        // 调用交易接口计算还款费用
        ConfirmResponseDTO confirmResponseDTO = consumeLoanDubboService.calculateCost(loanConfirmRequestDTO);
        
        LoanFeeCalculationResponseVO loanFeeCalculationResponseVO = new LoanFeeCalculationResponseVO();
        loanFeeCalculationResponseVO.setHandAmount(confirmResponseDTO.getHandAmount());
        loanFeeCalculationResponseVO.setPlatformManagerFee(confirmResponseDTO.getPlatformManageFee());
        loanFeeCalculationResponseVO.setGuaranteServiceFee(confirmResponseDTO.getGuaranteServiceFee());
        loanFeeCalculationResponseVO.setLoanInterest(confirmResponseDTO.getLoanInterestFee());
        loanFeeCalculationResponseVO.setBorrowerRate(confirmResponseDTO.getLoanInterestRate());
        loanFeeCalculationResponseVO.setLoanTerm(confirmResponseDTO.getLoanTerm());
        loanFeeCalculationResponseVO.setRepaymentTotalAmount(confirmResponseDTO.getTotalRepayAmount());
        loanFeeCalculationResponseVO.setRepaymentWay(confirmResponseDTO.getRepaymentWay().getValue());
        loanFeeCalculationResponseVO.setOverdueFeeRate(confirmResponseDTO.getOverdueFeeRate());
        loanFeeCalculationResponseVO.setPlatformManageFeeRate(confirmResponseDTO.getPlatformManageFeeRate());
        loanFeeCalculationResponseVO.setGuaranteeServiceFeeRate(confirmResponseDTO.getGuaranteeServiceFeeRate());
        loanFeeCalculationResponseVO.setWithdrawFee(confirmResponseDTO.getWithdrawFee());
        loanFeeCalculationResponseVO.setWithdrawFeeRate(confirmResponseDTO.getWithdrawFeeRate());
        
        // 银行卡信息
        BankCardDTO bankCardDTO = bankCardDubboService.getUserBankCardInfo(userId);
        loanFeeCalculationResponseVO.setBankCard(transToBankCardVO(bankCardDTO));

        return Result.with(loanFeeCalculationResponseVO);
    }    
    
    @PostMapping("/repaymentPlan")
    @ApiOperation("还款计划")
    public Result<List<RepaymentPlanResponseVO>> repaymentPlan(@RequestBody @Valid LoanRepaymentPlanRequestDTO request) {
		ConfirmLoanRepaymentPlanRequestDTO loanConfirmRequestDTO = new ConfirmLoanRepaymentPlanRequestDTO(
				request.getLoanAmount(), request.getLoanTerm(), PrincipalContext.getUserId(), ProjectTypeEnum.CONSUME_LOAN.getValue());
		List<RepaymentPlanDTO> repaymentPlanDTOList = speedLoanService.repaymentPlan(loanConfirmRequestDTO);
        return Result.with(repaymentPlanDTOTransform(repaymentPlanDTOList));
    }
    
    @PostMapping("/loanSubmit")
    @ApiOperation("消费贷申请提交")
    public Result<LoanSubmitCommResVO> loanSubmit(@RequestBody @Valid LoanSubmitReqVO loanSubmitReqVO, HttpServletRequest request) {
        String reqVOJSONString = JSON.toJSONString(loanSubmitReqVO);
        LoanSubmitReqDTO reqDTO = JSON.parseObject(reqVOJSONString, LoanSubmitReqDTO.class);
        reqDTO.getDeviceInfo().setIp(RequestUtil.getUserRealIP(request));
        reqDTO.setUserId(PrincipalContext.getUserId());
        reqDTO.setLoanSubmitTypeEnum(LoanSubmitTypeEnum.CONSUME_LOAN);
        LoanSubmitCommResDTO resDTO = loanSubmitDubboService.loanSubmit(reqDTO);
        return Result.with(obtainLoanSubmitCommResVO(resDTO));
    }
    
    @PostMapping("/loanBackSubmit")
    @ApiOperation("消费贷审核退回重新申请")
    public Result<LoanSubmitCommResVO> loanBackSubmit(@RequestBody @Valid LoanBackSubmitReqVO loanBackSubmitReqVO, HttpServletRequest request) {
        String reqVOJSONString = JSON.toJSONString(loanBackSubmitReqVO);
        LoanBackSubmitReqDTO reqDTO = JSON.parseObject(reqVOJSONString, LoanBackSubmitReqDTO.class);
        reqDTO.getDeviceInfo().setIp(RequestUtil.getUserRealIP(request));
        reqDTO.setUserId(PrincipalContext.getUserId());
        reqDTO.setLoanSubmitTypeEnum(LoanSubmitTypeEnum.CONSUME_LOAN);
        LoanSubmitCommResDTO resDTO = loanSubmitDubboService.loanBackSubmit(reqDTO);
        return Result.with(obtainLoanSubmitCommResVO(resDTO));
    }    

    @PostMapping("/loanReConfirmSubmit")
    @ApiOperation("消费贷提额重新申请")
    public Result<LoanSubmitCommResVO> loanReConfirmSubmit(@RequestBody @Valid LoanReConfirmSubmitReqVO loanReConfirmSubmitReqVO) {
        LoanReConfirmSubmitReqDTO reqDTO = new LoanReConfirmSubmitReqDTO();
        BeanUtils.copyProperties(loanReConfirmSubmitReqVO,reqDTO);
        reqDTO.setUserId(PrincipalContext.getUserId());
        reqDTO.setLoanSubmitTypeEnum(LoanSubmitTypeEnum.CONSUME_LOAN);
        LoanSubmitCommResDTO resDTO = loanSubmitDubboService.loanReConfirmSubmit(reqDTO);
        return Result.with(obtainLoanSubmitCommResVO(resDTO));
    }
    
    @PostMapping("/loanAuditConfirm")
    @ApiOperation("消费贷审核通过确认借款")
    public Result<LoanSubmitCommResVO> loanAuditConfirm(@RequestBody @Valid LoanAuditConfirmReqVO loanAuditConfirmReqVO) {
        LoanAuditConfirmReqDTO reqDTO = new LoanAuditConfirmReqDTO();
        BeanUtils.copyProperties(loanAuditConfirmReqVO,reqDTO);
        reqDTO.setUserId(PrincipalContext.getUserId());
        reqDTO.setLoanSubmitTypeEnum(LoanSubmitTypeEnum.CONSUME_LOAN);
        LoanSubmitCommResDTO resDTO = loanSubmitDubboService.loanAuditConfirm(reqDTO);
        return Result.with(obtainLoanSubmitCommResVO(resDTO));
    }    
 
    private List<RepaymentPlanResponseVO> repaymentPlanDTOTransform(List<RepaymentPlanDTO> repaymentPlanDTOList) {
        List<RepaymentPlanResponseVO> repaymentPlanList = null;
        if(CollectionUtils.isEmpty(repaymentPlanDTOList)) {
        	return repaymentPlanList;
        }
		repaymentPlanList = new ArrayList<>(repaymentPlanDTOList.size());
		for (RepaymentPlanDTO repaymentPlanDTO : repaymentPlanDTOList) {
			RepaymentPlanResponseVO planResponseVO = new RepaymentPlanResponseVO();
			BeanUtils.copyProperties(repaymentPlanDTO, planResponseVO);
			repaymentPlanList.add(planResponseVO);
		}
        return repaymentPlanList;
    }    
    
    private LoanSubmitCommResVO obtainLoanSubmitCommResVO(LoanSubmitCommResDTO resDTO){
        LoanSubmitCommResVO resVO = new LoanSubmitCommResVO();
        BeanUtils.copyProperties(resDTO, resVO);
        resVO.setCheckStatus(resDTO.getStatus());
        return resVO;
    }
    
	private BankCardVO transToBankCardVO(BankCardDTO dto) {
		BankTypeDTO bankTypeDTO = dto.getBankType();
		BankTypeVO bankTypeVO = new BankTypeVO();
		bankTypeVO.setBankTypeId(bankTypeDTO.getBankTypeId());
		bankTypeVO.setBankCode(bankTypeDTO.getBankCode());
		bankTypeVO.setBankName(bankTypeDTO.getBankName());

		BankCardVO vo = new BankCardVO();
		vo.setBankCardId(dto.getBankCardId());
		vo.setBankAccountNo(dto.getBankAccountNo());
		vo.setBankType(bankTypeVO);
		return vo;
	}    
}